use chrono::Local;
use reqwest::{Client, Method};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::time::Duration;
use tokio::time;

#[derive(Debug, Deserialize, Serialize, Clone)]
struct Config {
    tasks: Vec<TaskConfig>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
struct TaskConfig {
    name: String,
    url: String,
    method: String,
    interval_seconds: u64,
    #[serde(default)]
    headers: HashMap<String, String>,
    #[serde(default)]
    body: Option<String>,
}

struct TaskExecutor {
    config: TaskConfig,
    client: Client,
}

impl TaskExecutor {
    fn new(config: TaskConfig) -> Self {
        Self {
            config,
            client: Client::new(),
        }
    }

    async fn execute(&self) -> Result<(), Box<dyn std::error::Error>> {
        let timestamp = Local::now().format("%Y-%m-%d %H:%M:%S");
        println!(
            "[{}] 执行任务: {} -> {}",
            timestamp, self.config.name, self.config.url
        );

        let method = match self.config.method.to_uppercase().as_str() {
            "GET" => Method::GET,
            "POST" => Method::POST,
            "PUT" => Method::PUT,
            "DELETE" => Method::DELETE,
            _ => {
                println!("  ❌ 不支持的请求方法: {}", self.config.method);
                return Ok(());
            }
        };

        let mut request = self.client.request(method, &self.config.url);

        // 添加请求头
        for (key, value) in &self.config.headers {
            request = request.header(key, value);
        }

        // 添加请求体（如果存在）
        if let Some(body) = &self.config.body {
            request = request.body(body.clone());
        }

        match request.send().await {
            Ok(response) => {
                let status = response.status();
                println!("  ✓ 响应状态: {}", status);
                
                // 尝试读取响应体的前200个字符
                match response.text().await {
                    Ok(body) => {
                        let preview = if body.len() > 200 {
                            format!("{}...", &body[..200])
                        } else {
                            body
                        };
                        println!("  ✓ 响应预览: {}", preview);
                    }
                    Err(e) => println!("  ⚠ 无法读取响应体: {}", e),
                }
            }
            Err(e) => {
                println!("  ❌ 请求失败: {}", e);
            }
        }

        Ok(())
    }

    async fn run(&self) {
        let mut interval = time::interval(Duration::from_secs(self.config.interval_seconds));
        
        loop {
            interval.tick().await;
            if let Err(e) = self.execute().await {
                eprintln!("  ❌ 任务执行错误: {}", e);
            }
        }
    }
}

fn load_config(path: &str) -> Result<Config, Box<dyn std::error::Error>> {
    let content = fs::read_to_string(path)?;
    let config: Config = toml::from_str(&content)?;
    Ok(config)
}

#[tokio::main]
async fn main() {
    println!("🚀 定时请求任务系统启动");
    println!("==================================");

    // 读取配置文件
    let config = match load_config("config.toml") {
        Ok(config) => config,
        Err(e) => {
            eprintln!("❌ 无法读取配置文件: {}", e);
            eprintln!("请确保 config.toml 文件存在且格式正确");
            return;
        }
    };

    if config.tasks.is_empty() {
        println!("⚠ 配置文件中没有定义任何任务");
        return;
    }

    println!("📋 加载了 {} 个任务:", config.tasks.len());
    for task in &config.tasks {
        println!(
            "  - {} ({} {}, 每 {} 秒)",
            task.name, task.method, task.url, task.interval_seconds
        );
    }
    println!("==================================\n");

    // 创建所有任务并并发运行
    let mut handles = vec![];

    for task_config in config.tasks {
        let handle = tokio::spawn(async move {
            let executor = TaskExecutor::new(task_config);
            executor.run().await;
        });
        handles.push(handle);
    }

    // 等待所有任务完成（实际上会一直运行）
    for handle in handles {
        if let Err(e) = handle.await {
            eprintln!("❌ 任务线程错误: {}", e);
        }
    }
}
